/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "C_几何数据变换.h"


C_几何数据变换::C_几何数据变换()
{
	Matrix4X4f_Identity(m_Matrix);
}


C_几何数据变换::~C_几何数据变换()
{
}






C_几何数据变换& C_几何数据变换::f_RX(float32 角度) {
	float32 mat[16];
	Matrix4X4_BuildRotationXMat(mat, 角度);
	f_Mat4X4_相乘(m_Matrix, mat);
	return *this;
}
C_几何数据变换&  C_几何数据变换::f_RY(float32 角度) {
	float32 mat[16];
	Matrix4X4_BuildRotationYMat(mat, 角度);
	f_Mat4X4_相乘(m_Matrix, mat);
	return *this;
}
C_几何数据变换&  C_几何数据变换::f_RZ(float32 角度) {
	float32 mat[16];
	Matrix4X4_BuildRotationZMat(mat, 角度);
	f_Mat4X4_相乘(m_Matrix, mat);
	return *this;
}



C_几何数据变换&  C_几何数据变换::f_MX(float32 m) {
	float32 mat[16];
	Matrix4X4_BuildXMat(mat, m);
	f_Mat4X4_相乘(m_Matrix, mat);
	return *this;
}
C_几何数据变换&  C_几何数据变换::f_MY(float32 m) {
	float32 mat[16];
	Matrix4X4_BuildYMat(mat, m);
	f_Mat4X4_相乘(m_Matrix, mat);
	return *this;
}
C_几何数据变换&  C_几何数据变换::f_MZ(float32 m) {
	float32 mat[16];
	Matrix4X4_BuildZMat(mat, m);
	f_Mat4X4_相乘(m_Matrix, mat);
	return *this;
}
C_几何数据变换&  C_几何数据变换::f_MXYZ(const float32 m[3]) {
	Matrix4X4_Location(m_Matrix, m);
	return *this;
}


C_几何数据变换&  C_几何数据变换::f_SX(float32 s) {
	float32 mat[16];
	Matrix4X4_BuildScaleX(mat, s);
	f_Mat4X4_相乘(m_Matrix, mat);
	return *this;
}
C_几何数据变换&  C_几何数据变换::f_SY(float32 s) {
	float32 mat[16];
	Matrix4X4_BuildScaleY(mat, s);
	f_Mat4X4_相乘(m_Matrix, mat);
	return *this;
}
C_几何数据变换&  C_几何数据变换::f_SZ(float32 s) {
	float32 mat[16];
	Matrix4X4_BuildScaleZ(mat, s);
	f_Mat4X4_相乘(m_Matrix, mat);
	return *this;
}
C_几何数据变换&  C_几何数据变换::f_SXYZ(const vec3& s) {
	float32 mat[16];
	Matrix4X4_BuildScale(mat, (const float32*)&s);
	f_Mat4X4_相乘(m_Matrix, mat);
	return *this;
}

C_几何数据变换& C_几何数据变换::operator *= (const float32* mat) {
	f_Mat4X4_相乘(m_Matrix, mat);
	return *this;
}

Mat44f C_几何数据变换::operator * (const Mat44f& mat) {
	Mat44f newMat;
	f_Mat4X4_相乘((float32*)&newMat, m_Matrix, (const float32*)&mat);
	return newMat;
}




vec3 C_几何数据变换::f_Euler() {
	vec3 ea;

	ea.x = atan2(m_Matrix[9], m_Matrix[10]);
	ea.y = atan2(-m_Matrix[8], sqrtf(m_Matrix[9] * m_Matrix[9] + m_Matrix[10] * m_Matrix[10]));
	ea.z = atan2(m_Matrix[4], m_Matrix[0]);

	return ea;
}

void C_几何数据变换::f_变换(std::vector<vec3>& vert, ui2_32 range)
{
	for (uint32 i = range.x; i < range.y; ++i) {
		auto& v = vert[i];
		vec4 tmpV = { v.x, v.y, v.z, 1.0 };
		vec4 newV = { 0.0,0.0,0.0,0.0 };
		Mat变换坐标4(m_Matrix, (float32*)&tmpV, (float32*)&newV);

		v.x = newV.x;
		v.y = newV.y;
		v.z = newV.z;
	}
	
}

void C_几何数据变换::f_变换(E_vec3元素指针* re, const E_vec3元素指针& e) {
	for (uint32 i = 0; i < e.count; ++i) {
		re->point[i] = (this->operator<<(e.point[i]));
	}
}
void C_几何数据变换::f_变换(E_vec3元素指针* re, const std::vector<vec3>& vert) {
	for (uint32 i = 0; i < vert.size(); ++i) {
		re->point[i] = this->operator<<(vert[i]);
	}
}

void C_几何数据变换::f_Invert(const float32 * mat)
{
	f_Matrix4X4_InvertMatrixf2(mat, m_Matrix);
}


void C_几何数据变换::f_正交投影(const vec4& view, float32* mat) {
	mat[0] = 1.0 / (view.x/2.0); mat[1] = 0.0; mat[2] = 0.0; mat[3] = 0.0;
	mat[4] = 0.0; mat[5] = 1.0 / (view.y / 2.0); mat[6] = 0.0; mat[7] = 0.0;
	mat[8] = 0.0; mat[9] = 0.0; mat[10] = 1.0 / ((view.w - view.z) / 2.0); mat[11] = (view.w + view.z) / (view.w - view.z);
	mat[12] = 0.0; mat[13] = 0.0; mat[14] = 0.0; mat[15] = 1.0;
}







C_Quaternion::C_Quaternion()
{
	m_X = 0.0; m_Y = 0.0; m_Z = 0.0; m_W = 1.0;
}

C_Quaternion::~C_Quaternion()
{
}

void C_Quaternion::f_FromAxis(vec3 v, float32 angle)
{
	float scale = sinf(angle / 2) / sqrtf(vec_dot(v, v));

	m_X = scale * v.x;
	m_Y = scale * v.y;
	m_Z = scale * v.z;
	m_W = cosf(angle / 2);
	return;

	float32 d = v.x*v.x + v.y*v.y + v.z*v.z;
	if (d < 01e-7) return;

	d = 1.0 / sqrtf(d);
	vec_mul(&v, d);

	vec2 cs;
	cs.x = cos(0.5*angle);
	cs.y = sin(0.5*angle);

	m_W = cs.x;
	m_X = cs.y * v.x;
	m_Y = cs.y * v.y;
	m_Z = cs.y * v.z;

	return;

	angle = M_角度转弧度(angle);
	angle *= 0.5;
	vec3 vn = v;
	vec_normalize(vn);

	float32 sinAngle = sin(angle);

	m_X = vn.x * sinAngle;
	m_Y = vn.y * sinAngle;
	m_Z = vn.z * sinAngle;
	m_W = cos(sinAngle);

}

void C_Quaternion::f_FromDir(vec3 dir) {
	float32 q2 = vec_mag2(dir) / 4.0f;

	vec3 xyz;
	if (q2 < 1) {
		m_W = sqrtf(1.0f - q2);
		xyz = f_vec_normalizDiv(dir, 2);
	}
	else {
		m_W = 1.0f / sqrtf(1.0f + q2);
		xyz = vec_mul(dir, m_W / 2.0);
	}
	m_X = xyz.x;
	m_Y = xyz.y;
	m_Z = xyz.z;

	return;



	float r = dir.x;
	float p = dir.y;
	float y = dir.z;
	float cr = cosf(r / 2.0f); float sr = sinf(r / 2.0f);
	float cp = cosf(p / 2.0f); float sp = sinf(p / 2.0f);
	float cy = cosf(y / 2.0f); float sy = sinf(y / 2.0f);

	m_X = sr * cp * cy - cr * sp * sy;
	m_Y = cr * sp * cy + sr * cp * sy;
	m_Z = cr * cp * sy - sr * sp * cy;
	m_W = cr * cp * cy + sr * sp * sy;

}



Mat44f C_Quaternion::f_getMar4X4() const {
	/*float a = q[3];
	float b = q[0];
	float c = q[1];
	float d = q[2];*/
	/*float a2 = m_W * m_W;
	float b2 = m_X * m_X;
	float c2 = m_Y * m_Y;
	float d2 = m_Z * m_Z;*/

	Mat44f M;

	/*M.m00 = a2 + b2 - c2 - d2;
	M.m01 = 2.f*(m_X*m_Y + m_W * m_Z);
	M.m02 = 2.f*(m_X*m_Z - m_W * m_Y);
	M.m03 = 0.f;

	M.m10 = 2 * (m_X*m_Y - m_W * m_Z);
	M.m11 = a2 - b2 + c2 - d2;
	M.m12 = 2.f*(m_Y*m_Z + m_W * m_Z);
	M.m13 = 0.f;

	M.m20 = 2.f*(m_X*m_Z + m_W * m_Y);
	M.m21 = 2.f*(m_Y*m_Z - m_W * m_X);
	M.m22 = a2 - b2 - c2 + d2;
	M.m23 = 0.f;

	M.m30 = M.m31 = M.m32 = 0.f;
	M.m33 = 1.f;*/


	/*M.m00 = a2 + b2 - c2 - d2;
	M.m10 = 2.f*(m_X*m_Y + m_W * m_Z);
	M.m20 = 2.f*(m_X*m_Z - m_W * m_Y);
	M.m30 = 0.f;

	M.m01 = 2 * (m_X*m_Y - m_W * m_Z);
	M.m11 = a2 - b2 + c2 - d2;
	M.m21 = 2.f*(m_Y*m_Z + m_W * m_Z);
	M.m31 = 0.f;

	M.m02 = 2.f*(m_X*m_Z + m_W * m_Y);
	M.m12 = 2.f*(m_Y*m_Z - m_W * m_X);
	M.m22 = a2 - b2 - c2 + d2;
	M.m32 = 0.f;

	M.m03 = M.m13 = M.m23 = 0.f;
	M.m33 = 1.f;

	return M;*/


	float x = m_X;
	float y = m_Y;
	float z = m_Z;
	float w = m_W;

	M.m00 = 1 - 2 * y*y - 2 * z*z;
	M.m01 = 2 * x*y - 2 * z*w;
	M.m02 = 2 * x*z + 2 * y*w;
	M.m03 = 0.0;

	M.m10 = 2 * x*y + 2 * z*w;
	M.m11 = 1 - 2 * x*x - 2 * z*z;
	M.m12 = 2 * y*z - 2 * x*w;
	M.m13 = 0.0;

	M.m20 = 2 * x*z - 2 * y*w;
	M.m21 = 2 * y*z + 2 * x*w;
	M.m22 = 1 - 2 * x*x - 2 * y*y;
	M.m23 = 0.0;

	M.m30 = M.m31 = M.m32 = 0.f;
	M.m33 = 1.f;
	return M;


	float x2 = m_X * m_X;
	float y2 = m_Y * m_Y;
	float z2 = m_Z * m_Z;
	float xy = m_X * m_Y;
	float xz = m_X * m_Z;
	float yz = m_Y * m_Z;
	float wx = m_W * m_X;
	float wy = m_W * m_Y;
	float wz = m_W * m_Z;

	return { 1.0f - 2.0f * (y2 + z2), 2.0f * (xy + wz), 2.0f * (xz - wy), 0.0f,
	2.0f * (xy - wz), 1.0f - 2.0f * (x2 + z2), 2.0f * (yz + wx), 0.0f,
	2.0f * (xz + wy), 2.0f * (yz - wx), 1.0f - 2.0f * (x2 + y2), 0.0f,
	0.0f, 0.0f, 0.0f, 1.0f };

	return { 1.0f - 2.0f * (y2 + z2), 2.0f * (xy - wz), 2.0f * (xz + wy), 0.0f,
		2.0f * (xy + wz), 1.0f - 2.0f * (x2 + z2), 2.0f * (yz - wx), 0.0f,
		2.0f * (xz - wy), 2.0f * (yz + wx), 1.0f - 2.0f * (x2 + y2), 0.0f,
		0.0f, 0.0f, 0.0f, 1.0f };

}
